package org.cybzacg.encryption.core;

import org.cybzacg.encryption.context.EncryptionContext;
import org.cybzacg.encryption.model.EncryptionResult;
import org.cybzacg.encryption.model.ValidationResult;
import org.cybzacg.encryption.enums.EncryptionAlgorithm;
import org.cybzacg.encryption.enums.EncryptionStatus;
import org.cybzacg.encryption.exception.EncryptionException;

import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 抽象加密器基类
 * 提供加密器的基础功能和通用实现
 * 
 * @author encryption team
 * @version 1.0
 */
public abstract class AbstractEncryptor implements Encryptor {

    protected final EncryptionAlgorithm algorithm;
    protected final AtomicBoolean initialized;
    protected final AtomicLong operationCount;
    protected final AtomicLong totalProcessingTime;
    protected final Map<String, Object> metadata;

    /**
     * 构造函数
     * 
     * @param algorithm 算法
     */
    protected AbstractEncryptor(EncryptionAlgorithm algorithm) {
        if (algorithm == null) {
            throw new IllegalArgumentException("Algorithm cannot be null");
        }
        this.algorithm = algorithm;
        this.initialized = new AtomicBoolean(false);
        this.operationCount = new AtomicLong(0);
        this.totalProcessingTime = new AtomicLong(0);
        this.metadata = new ConcurrentHashMap<>();
    }

    @Override
    public EncryptionAlgorithm getAlgorithm() {
        return algorithm;
    }

    @Override
    public void initialize(EncryptionContext context) {
        if (context == null) {
            throw new IllegalArgumentException("Context cannot be null");
        }

        if (initialized.compareAndSet(false, true)) {
            doInitialize(context);
        }
    }

    @Override
    public EncryptionResult encrypt(byte[] data, EncryptionContext context) {
        return executeOperation("encrypt", data, context, this::doEncrypt);
    }

    @Override
    public EncryptionResult decrypt(byte[] encryptedData, EncryptionContext context) {
        return executeOperation("decrypt", encryptedData, context, this::doDecrypt);
    }

    @Override
    public ValidationResult validate(EncryptionContext context) {
        try {
            // 基本验证
            ValidationResult basicValidation = validateBasic(context);
            if (!basicValidation.isValid()) {
                return basicValidation;
            }

            // 算法特定验证
            ValidationResult algorithmValidation = validateAlgorithm(context);
            if (!algorithmValidation.isValid()) {
                return algorithmValidation;
            }

            // 子类自定义验证
            return doValidate(context);

        } catch (Exception e) {
            return ValidationResult.failure("Validation error", e.getMessage(), context);
        }
    }

    @Override
    public boolean supports(EncryptionContext context) {
        if (context == null || !initialized.get()) {
            return false;
        }

        // 检查算法匹配
        if (algorithm != context.getAlgorithm()) {
            return false;
        }

        // 检查加密类型匹配
        if (algorithm.getType() != context.getEncryptionType()) {
            return false;
        }

        // 子类自定义支持检查
        return doSupports(context);
    }

    @Override
    public org.cybzacg.encryption.enums.EncryptionType getType() {
        return algorithm.getType();
    }

    @Override
    public int getPriority() {
        return 100; // 默认优先级
    }

    @Override
    public String getDescription() {
        return algorithm.getDescription();
    }

    @Override
    public String getProvider() {
        return algorithm.getName();
    }

    @Override
    public Map<String, Object> getMetadata() {
        return new ConcurrentHashMap<>(metadata);
    }

    @Override
    public long getOperationCount() {
        return operationCount.get();
    }

    @Override
    public long getAverageProcessingTime() {
        long count = operationCount.get();
        if (count == 0) {
            return 0;
        }
        return totalProcessingTime.get() / count;
    }

    @Override
    public void reset() {
        operationCount.set(0);
        totalProcessingTime.set(0);
        metadata.clear();
        doReset();
    }

    @Override
    public void close() {
        initialized.set(false);
        doClose();
    }

    /**
     * 执行加密操作
     * 
     * @param data    待加密数据
     * @param context 上下文
     * @return 加密结果
     */
    protected abstract byte[] doEncrypt(byte[] data, EncryptionContext context);

    /**
     * 执行解密操作
     * 
     * @param encryptedData 加密数据
     * @param context       上下文
     * @return 解密结果
     */
    protected abstract byte[] doDecrypt(byte[] encryptedData, EncryptionContext context);

    /**
     * 执行初始化
     * 
     * @param context 上下文
     */
    protected abstract void doInitialize(EncryptionContext context);

    /**
     * 执行验证
     * 
     * @param context 上下文
     * @return 验证结果
     */
    protected abstract ValidationResult doValidate(EncryptionContext context);

    /**
     * 检查是否支持上下文
     * 
     * @param context 上下文
     * @return 是否支持
     */
    protected abstract boolean doSupports(EncryptionContext context);

    /**
     * 执行重置
     */
    protected void doReset() {
        // 默认空实现，子类可以重写
    }

    /**
     * 执行关闭
     */
    protected void doClose() {
        // 默认空实现，子类可以重写
    }

    /**
     * 执行操作（加密或解密）
     * 
     * @param operation     操作名称
     * @param data          数据
     * @param context       上下文
     * @param operationFunc 操作函数
     * @return 操作结果
     */
    private EncryptionResult executeOperation(String operation, byte[] data,
            EncryptionContext context,
            OperationFunction operationFunc) {
        if (!initialized.get()) {
            return EncryptionResult.failure(
                    EncryptionStatus.CONFIGURATION_ERROR,
                    "Encryptor not initialized",
                    context);
        }

        long startTime = System.currentTimeMillis();
        try {
            // 验证数据
            if (data == null) {
                return EncryptionResult.failure(
                        EncryptionStatus.INVALID_DATA_FORMAT,
                        "Data cannot be null",
                        context);
            }

            // 验证上下文
            if (!supports(context)) {
                return EncryptionResult.failure(
                        EncryptionStatus.CONFIGURATION_ERROR,
                        "Context not supported",
                        context);
            }

            // 执行操作
            byte[] result = operationFunc.apply(data, context);

            // 更新统计信息
            long duration = System.currentTimeMillis() - startTime;
            operationCount.incrementAndGet();
            totalProcessingTime.addAndGet(duration);

            // 返回成功结果
            return new EncryptionResult.Builder()
                    .status(EncryptionStatus.SUCCESS)
                    .data(result)
                    .algorithm(algorithm)
                    .context(context)
                    .processingTime(duration)
                    .build();

        } catch (Exception e) {
            long duration = System.currentTimeMillis() - startTime;
            operationCount.incrementAndGet();
            totalProcessingTime.addAndGet(duration);

            EncryptionException ex = e instanceof EncryptionException ? (EncryptionException) e
                    : new EncryptionException(e.getMessage(), e);

            return EncryptionResult.error(ex, context);
        }
    }

    /**
     * 基本验证
     * 
     * @param context 上下文
     * @return 验证结果
     */
    private ValidationResult validateBasic(EncryptionContext context) {
        if (context == null) {
            return ValidationResult.failure("Context cannot be null", "Context is null", context);
        }

        if (!context.isValid()) {
            return ValidationResult.failure("Context is invalid", "Context validation failed", context);
        }

        if (context.getAlgorithm() != algorithm) {
            return ValidationResult.failure(
                    "Algorithm mismatch",
                    "Expected: " + algorithm + ", Actual: " + context.getAlgorithm(),
                    context);
        }

        return ValidationResult.success("Basic validation passed", context);
    }

    /**
     * 算法验证
     * 
     * @param context 上下文
     * @return 验证结果
     */
    private ValidationResult validateAlgorithm(EncryptionContext context) {
        // 检查密钥
        if (algorithm.isSymmetric() && context.getKey() == null) {
            return ValidationResult.failure("Key is required for symmetric encryption", "Missing key", context);
        }

        if (algorithm.isAsymmetric()) {
            if (context.getPublicKey() == null && context.getPrivateKey() == null) {
                return ValidationResult.failure("At least one key is required for asymmetric encryption",
                        "Missing keys", context);
            }
        }

        // 检查密钥长度
        if (context.getKey() != null && !algorithm.isValidKeySize(context.getKey().length * 8)) {
            return ValidationResult.failure(
                    "Invalid key size",
                    "Key size: " + (context.getKey().length * 8) + " bits",
                    context);
        }

        return ValidationResult.success("Algorithm validation passed", context);
    }

    /**
     * 操作函数接口
     */
    @FunctionalInterface
    private interface OperationFunction {
        byte[] apply(byte[] data, EncryptionContext context) throws Exception;
    }
}
